﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NovoGenus.Sockets.Http.Headers
{

    /// <summary>
    /// Ref: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
    /// Http version 1.1
    /// </summary>
    public class HttpRequestHeaders
    {

        public HttpRequestHeaders(string host, string uri)
        {
            _method = "GET";
            _requestUri = uri;
            _host = host;
            _acceptLanguage = "en-US,en;q=0.5"; //default
            _accept = new Media();
            _accept.MediaRange.Add("text/html");//default
            _accept.MediaRange.Add("application/xhtml+xml");//default
            _accept.MediaRange.Add("application/xml");//default
            _accept.AcceptParams.Add("q=0.9,*/*");//default
            _accept.AcceptExtensions.Add("q=0.8");//default
            _userAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch;)";//default
        }



        #region private properties
        private string _requestUri;
        private string _method;
        private string _host;
        private string _userAgent;
        private string _cacheControl;
        private string _acceptLanguage;
        private string _age;
        private Media _accept;
        private Charset _acceptCharset;
        private List<HttpEncoding> _acceptEncodings;
        private string _acceptRanges;
        private string _allow;
        private string _authorization;
        private string _connection;
        private string _contentEncoding;
        private string _contentLanguage;
        private string _contentLength;
        private string _contentLocation;
        private string _contentMD5;
        private string _contentRange;
        private string _contentType;
        private string _date;
        private string _eTag;
        private string _expect;
        private string _expires;
        private string _from;
        private string _ifMatch;
        private string _ifModifiedSince;
        private string _ifNoneMatch;
        private string _ifRange;
        private string _ifUnmodifiedSince;
        private string _lastModified;
        private string _location;
        private string _maxForwards;
        private string _pragma; //
        private string _proxyAuthenticate;
        private string _proxyAuthorization;
        private string _range;
        private string _referrer;
        private string _retryAfter;
        private string _server;
        private string _tE;
        private string _trailer;
        private string _transferEncoding;
        private string _upgrade;
        private string _vary;
        private string _via;
        private string _warning;
        private string _wwwAuthenticate;
        #endregion

        #region public


        public override string ToString()
        {
            string data = string.Concat(Method, " ", RequestUri);
            data = string.Concat(data, Host);
            data = string.Concat(data, Accept.ToString());
            data = string.Concat(data, AcceptLanguage);
            data = string.Concat(data, UserAgent);

            return string.Concat(data, "\r\n");
        }

        public byte[] GetBytes()
        {
            byte[] data = Encoding.UTF8.GetBytes(this.ToString());
            return data;
        }

        private string FormatRequestLine(string generalHeader, string requestHeader)
        {
            return !string.IsNullOrEmpty(requestHeader) ? string.Concat(generalHeader, ": ", requestHeader, "\r\n") : string.Empty;
        }


        public string Method
        {
            get
            {
                return _method;
            }
            set
            {
                _method = value;
            }
        }

        public string RequestUri
        {
            get
            {
                return string.Concat(_requestUri, " HTTP/1.1\r\n");
            }
            set
            {
                _requestUri = value;
            }
        }

        /// <summary>
        /// The Proxy-Authorization request-header field allows the client to identify itself (or its user) to a proxy which requires authentication. The Proxy-Authorization field value consists of credentials containing the authentication information of the user agent for the proxy and/or realm of the resource being requested.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.34
        /// </summary>
        public string ProxyAuthorization
        {
            get
            {
                return string.Concat("Proxy-Authorization: ", _proxyAuthorization, "\r\n");
            }
            set
            {
                _proxyAuthorization = value;
            }
        }

        /// <summary>
        /// The Proxy-Authenticate response-header field MUST be included as part of a 407 (Proxy Authentication Required) response. The field value consists of a challenge that indicates the authentication scheme and parameters applicable to the proxy for this Request-URI.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.33
        /// </summary>
        public string ProxyAuthenticate
        {
            get
            {
                return string.Concat("Proxy-Authenticate: ", _proxyAuthenticate, "\r\n");
            }
            set
            {
                _proxyAuthenticate = value;
            }
        }

        /// <summary>
        /// The Proxy-Authorization request-header field allows the client to identify itself (or its user) to a proxy which requires authentication. The Proxy-Authorization field value consists of credentials containing the authentication information of the user agent for the proxy and/or realm of the resource being requeste
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.34
        /// </summary>
        public string Range
        {
            get
            {
                return string.Concat("Proxy-Authorization: ", _proxyAuthorization, "\r\n");
            }
            set
            {
                _proxyAuthorization = value;
            }
        }

        ///// <summary>
        ///// Since all HTTP entities are represented in HTTP messages as sequences of bytes, the concept of a byte range is meaningful for any HTTP entity. (However, not all clients and servers need to support byte- range operations.)
        ///// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
        ///// </summary>
        //public string Range
        //{
        //    get
        //    {
        //        return string.Concat("Range: ", _range, "\r\n");
        //    }
        //    set
        //    {
        //        _range = value;
        //    }
        //}

        /// <summary>
        /// The Referer[sic] request-header field allows the client to specify, for the server's benefit, the address (URI) of the resource from which the Request-URI was obtained (the "referrer", although the header field is misspelled.) The Referer request-header allows a server to generate lists of back-links to resources for interest, logging, optimized caching, etc. It also allows obsolete or mistyped links to be traced for maintenance. The Referer field MUST NOT be sent if the Request-URI was obtained from a source that does not have its own URI, such as input from the user keyboard.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36
        /// </summary>
        public string RetryAfter
        {
            get
            {
                return string.Concat("Referer: ", _referrer, "\r\n");
            }
            set
            {
                _referrer = value;
            }
        }

        ///// <summary>
        ///// The Retry-After response-header field can be used with a 503 (Service Unavailable) response to indicate how long the service is expected to be unavailable to the requesting client. This field MAY also be used with any 3xx (Redirection) response to indicate the minimum time the user-agent is asked wait before issuing the redirected request. The value of this field can be either an HTTP-date or an integer number of seconds (in decimal) after the time of the response.
        ///// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.37
        ///// </summary>
        //public string RetryAfter
        //{
        //    get
        //    {
        //        return string.Concat("Retry-After: ", _retryAfter, "\r\n");
        //    }
        //    set
        //    {
        //        _retryAfter = value;
        //    }
        //}

        /// <summary>
        /// The Server response-header field contains information about the software used by the origin server to handle the request. The field can contain multiple product tokens (section 3.8) and comments identifying the server and any significant subproducts. The product tokens are listed in order of their significance for identifying the application.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.38
        /// </summary>
        public string Server
        {
            get
            {
                return string.Concat("Server: ", _server, "\r\n");
            }
            set
            {
                _server = value;
            }
        }

        /// <summary>
        /// The TE request-header field indicates what extension transfer-codings it is willing to accept in the response and whether or not it is willing to accept trailer fields in a chunked transfer-coding. Its value may consist of the keyword "trailers" and/or a comma-separated list of extension transfer-coding names with optional accept parameters
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.39
        /// </summary>
        public string Trailer
        {
            get
            {
                return string.Concat("TE: ", _tE, "\r\n");
            }
            set
            {
                _tE = value;
            }
        }

        ///// <summary>
        ///// The Trailer general field value indicates that the given set of header fields is present in the trailer of a message encoded with chunked transfer-coding.
        ///// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.40
        ///// </summary>
        //public string Trailer
        //{
        //    get
        //    {
        //        return string.Concat("Trailer: ", _trailer, "\r\n");
        //    }
        //    set
        //    {
        //        _trailer = value;
        //    }
        //}

        /// <summary>
        /// The Transfer-Encoding general-header field indicates what (if any) type of transformation has been applied to the message body in order to safely transfer it between the sender and the recipient. This differs from the content-coding in that the transfer-coding is a property of the message, not of the entity.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.41
        /// </summary>
        public string TransferEncoding
        {
            get
            {
                return string.Concat("Transfer-Encoding: ", _transferEncoding, "\r\n");
            }
            set
            {
                _transferEncoding = value;
            }
        }

        /// <summary>
        /// The Upgrade general-header allows the client to specify what additional communication protocols it supports and would like to use if the server finds it appropriate to switch protocols. The server MUST use the Upgrade header field within a 101 (Switching Protocols) response to indicate which protocol(s) are being switched.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.42
        /// </summary>
        public string Upgrade
        {
            get
            {
                return string.Concat("Upgrade: ", _upgrade, "\r\n");
            }
            set
            {
                _upgrade = value;
            }
        }

        /// <summary>
        /// The Vary field value indicates the set of request-header fields that fully determines, while the response is fresh, whether a cache is permitted to use the response to reply to a subsequent request without revalidation. For uncacheable or stale responses, the Vary field value advises the user agent about the criteria that were used to select the representation. A Vary field value of "*" implies that a cache cannot determine from the request headers of a subsequent request whether this response is the appropriate representation.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44s
        /// </summary>
        public string Via
        {
            get
            {
                return string.Concat("Vary: ", _vary, "\r\n");
            }
            set
            {
                _vary = value;
            }
        }

        ///// <summary>
        ///// The Via general-header field MUST be used by gateways and proxies to indicate the intermediate protocols and recipients between the user agent and the server on requests, and between the origin server and the client on responses. It is analogous to the "Received" field of RFC 822 [9] and is intended to be used for tracking message forwards, avoiding request loops, and identifying the protocol capabilities of all senders along the request/response chain
        ///// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.45
        ///// </summary>
        //public string Via
        //{
        //    get
        //    {
        //        return string.Concat("Via: ", _via, "\r\n");
        //    }
        //    set
        //    {
        //        _via = value;
        //    }
        //}

        /// <summary>
        /// The Warning general-header field is used to carry additional information about the status or transformation of a message which might not be reflected in the message. This information is typically used to warn about a possible lack of semantic transparency from caching operations or transformations applied to the entity body of the message.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.46
        /// </summary>
        public string Warning
        {
            get
            {
                return string.Concat("Warning: ", _warning, "\r\n");
            }
            set
            {
                _warning = value;
            }
        }

        /// <summary>
        /// The WWW-Authenticate response-header field MUST be included in 401 (Unauthorized) response messages. The field value consists of at least one challenge that indicates the authentication scheme(s) and parameters applicable to the Request-URI.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.47
        /// </summary>
        public string Pragma
        {
            get
            {
                return string.Concat("WWW-Authenticate: ", _wwwAuthenticate, "\r\n");
            }
            set
            {
                _wwwAuthenticate = value;
            }
        }

        ///// <summary>
        ///// The Pragma general-header field is used to include implementation- specific directives that might apply to any recipient along the request/response chain. All pragma directives specify optional behavior from the viewpoint of the protocol; however, some systems MAY require that behavior be consistent with the directives.
        ///// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.32
        ///// </summary>
        //public string Pragma
        //{
        //    get
        //    {
        //        return string.Concat("Pragma: ", _pragma, "\r\n");
        //    }
        //    set
        //    {
        //        _pragma = value;
        //    }
        //}

        /// <summary>
        /// The Max-Forwards request-header field provides a mechanism with the TRACE (section 9.8) and OPTIONS (section 9.2) methods to limit the number of proxies or gateways that can forward the request to the next inbound server. This can be useful when the client is attempting to trace a request chain which appears to be failing or looping in mid-chain.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.31
        /// </summary>
        public string MaxForwards
        {
            get
            {
                return string.Concat("Max-Forwards: ", _maxForwards, "\r\n");
            }
            set
            {
                _maxForwards = value;
            }
        }

        /// <summary>
        /// The Location response-header field is used to redirect the recipient to a location other than the Request-URI for completion of the request or identification of a new resource. For 201 (Created) responses, the Location is that of the new resource which was created by the request. For 3xx responses, the location SHOULD indicate the server's preferred URI for automatic redirection to the resource. The field value consists of a single absolute URI.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30
        /// </summary>
        public string Location
        {
            get
            {
                return string.Concat("Location: ", _location, "\r\n");
            }
            set
            {
                _location = value;
            }
        }

        /// <summary>
        /// The Last-Modified entity-header field indicates the date and time at which the origin server believes the variant was last modified.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.29
        /// </summary>
        public string LastModified
        {
            get
            {
                return string.Concat("Last-Modified: ", _lastModified, "\r\n");
            }
            set
            {
                _lastModified = value;
            }
        }

        /// <summary>
        /// The If-Unmodified-Since request-header field is used with a method to make it conditional. If the requested resource has not been modified since the time specified in this field, the server SHOULD perform the requested operation as if the If-Unmodified-Since header were not present.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.28
        /// </summary>
        public string IfUnmodifiedSince
        {
            get
            {
                return string.Concat("If-Unmodified-Since: ", _ifUnmodifiedSince, "\r\n");
            }
            set
            {
                _ifUnmodifiedSince = value;
            }
        }

        /// <summary>
        /// If a client has a partial copy of an entity in its cache, and wishes to have an up-to-date copy of the entire entity in its cache, it could use the Range request-header with a conditional GET (using either or both of If-Unmodified-Since and If-Match.) However, if the condition fails because the entity has been modified, the client would then have to make a second request to obtain the entire current entity-body.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.27
        /// </summary>
        public string IfRange
        {
            get
            {
                return string.Concat("If-Range: ", _ifRange, "\r\n");
            }
            set
            {
                _ifRange = value;
            }
        }

        /// <summary>
        /// The If-None-Match request-header field is used with a method to make it conditional. A client that has one or more entities previously obtained from the resource can verify that none of those entities is current by including a list of their associated entity tags in the If-None-Match header field. The purpose of this feature is to allow efficient updates of cached information with a minimum amount of transaction overhead. It is also used to prevent a method (e.g. PUT) from inadvertently modifying an existing resource when the client believes that the resource does not exist.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
        /// </summary>
        public string IfNoneMatch
        {
            get
            {
                return string.Concat("If-None-Match: ", _ifNoneMatch, "\r\n");
            }
            set
            {
                _ifNoneMatch = value;
            }
        }

        /// <summary>
        /// The If-Modified-Since request-header field is used with a method to make it conditional: if the requested variant has not been modified since the time specified in this field, an entity will not be returned from the server; instead, a 304 (not modified) response will be returned without any message-body.\
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
        /// </summary>
        public string IfModifiedSince
        {
            get
            {
                return string.Concat("If-Modified-Since: ", _ifModifiedSince, "\r\n");
            }
            set
            {
                _ifModifiedSince = value;
            }
        }


        /// <summary>
        /// The If-Match request-header field is used with a method to make it conditional. A client that has one or more entities previously obtained from the resource can verify that one of those entities is current by including a list of their associated entity tags in the If-Match header field. Entity tags are defined in section 3.11. The purpose of this feature is to allow efficient updates of cached information with a minimum amount of transaction overhead. It is also used, on updating requests, to prevent inadvertent modification of the wrong version of a resource. As a special case, the value "*" matches any current entity of the resource.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24
        /// </summary>
        public string IfMatch
        {
            get
            {
                return string.Concat("If-Match: ", _ifMatch, "\r\n");
            }
            set
            {
                _ifMatch = value;
            }
        }

        /// <summary>
        /// The From request-header field, if given, SHOULD contain an Internet e-mail address for the human user who controls the requesting user agent. The address SHOULD be machine-usable, as defined by "mailbox" in RFC 822 [9] as updated by RFC 1123 [8]:
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.22
        /// </summary>
        public string From
        {
            get
            {
                return string.Concat("From: ", _from, "\r\n");
            }
            set
            {
                _from = value;
            }
        }


        /// <summary>
        /// The Expires entity-header field gives the date/time after which the response is considered stale. A stale cache entry may not normally be returned by a cache (either a proxy cache or a user agent cache) unless it is first validated with the origin server (or with an intermediate cache that has a fresh copy of the entity). See section 13.2 for further discussion of the expiration model.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21
        /// </summary>
        public string Expires
        {
            get
            {
                return string.Concat("Expires: ", _expires, "\r\n");
            }
            set
            {
                _expires = value;
            }
        }

        /// <summary>
        /// The Expect request-header field is used to indicate that particular server behaviors are required by the clie
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20
        /// </summary>
        public string Expect
        {
            get
            {
                return string.Concat("Expect: ", _expect, "\r\n");
            }
            set
            {
                _expect = value;
            }
        }

        /// <summary>
        /// The ETag response-header field provides the current value of the entity tag for the requested variant. The headers used with entity tags are described in sections 14.24, 14.26 and 14.44. The entity tag MAY be used for comparison with other entities from the same resource (see section 13.3.3).
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19
        /// </summary>
        public string ETag
        {
            get
            {
                return string.Concat("Etag: ", _eTag, "\r\n");
            }
            set
            {
                _eTag = value;
            }
        }

        /// <summary>
        /// The Date general-header field represents the date and time at which the message was originated, having the same semantics as orig-date in RFC 822. The field value is an HTTP-date, as described in section 3.3.1; it MUST be sent in RFC 1123 [8]-date format.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18
        /// </summary>
        public string Date
        {
            get
            {
                return string.Concat("Date: ", _date, "\r\n");
            }
            set
            {
                _date = value;
            }
        }

        /// <summary>
        /// The Content-Type entity-header field indicates the media type of the entity-body sent to the recipient or, in the case of the HEAD method, the media type that would have been sent had the request been a GET.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
        /// </summary>
        public string ContentType
        {
            get
            {
                return string.Concat("Content-Type: ", _contentType, "\r\n");
            }
            set
            {
                _contentType = value;
            }
        }

        /// <summary>
        /// The Content-Range entity-header is sent with a partial entity-body to specify where in the full entity-body the partial body should be applied. Range units are defined in section 3.12.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
        /// </summary>
        public string ContentRange
        {
            get
            {
                return string.Concat("Content-Range: ", _contentRange, "\r\n");
            }
            set
            {
                _contentRange = value;
            }
        }

        /// <summary>
        /// The Content-MD5 entity-header field, as defined in RFC 1864 [23], is an MD5 digest of the entity-body for the purpose of providing an end-to-end message integrity check (MIC) of the entity-body. (Note: a MIC is good for detecting accidental modification of the entity-body in transit, but is not proof against malicious attacks.)
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.15
        /// </summary>
        public string ContentMD5
        {
            get
            {
                return string.Concat("Content-MD5: ", _contentMD5, "\r\n");
            }
            set
            {
                _contentMD5 = value;
            }
        }

        /// <summary>
        /// The Content-Location entity-header field MAY be used to supply the resource location for the entity enclosed in the message when that entity is accessible from a location separate from the requested resource's URI. A server SHOULD provide a Content-Location for the variant corresponding to the response entity; especially in the case where a resource has multiple entities associated with it, and those entities actually have separate locations by which they might be individually accessed, the server SHOULD provide a Content-Location for the particular variant which is returned.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.14
        /// </summary>
        public string ContentLocation
        {
            get
            {
                return string.Concat("Content-Location: ", _contentLocation, "\r\n");
            }
            set
            {
                _contentLocation = value;
            }
        }

        /// <summary>
        /// The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
        /// </summary>
        public string ContentLength
        {
            get
            {
                return string.Concat("Content-Length: ", _contentLength, "\r\n");
            }
            set
            {
                _contentLength = value;
            }
        }

        /// <summary>
        /// The Content-Language entity-header field describes the natural language(s) of the intended audience for the enclosed entity. Note that this might not be equivalent to all the languages used within the entity-body.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.12
        /// </summary>
        public string ContentLanguage
        {
            get
            {
                return string.Concat("Content-Language: ", _contentLanguage, "\r\n");
            }
            set
            {
                _contentLanguage = value;
            }
        }

        /// <summary>
        /// The Content-Encoding entity-header field is used as a modifier to the media-type. When present, its value indicates what additional content codings have been applied to the entity-body, and thus what decoding mechanisms must be applied in order to obtain the media-type referenced by the Content-Type header field. Content-Encoding is primarily used to allow a document to be compressed without losing the identity of its underlying media type.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
        /// </summary>
        public string ContentEncoding
        {
            get
            {
                return string.Concat("Content-Encoding: ", _contentEncoding, "\r\n");
            }
            set
            {
                _contentEncoding = value;
            }
        }


        /// <summary>
        /// The Connection general-header field allows the sender to specify options that are desired for that particular connection and MUST NOT be communicated by proxies over further connections.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10
        /// </summary>
        public string Connection
        {
            get
            {
                return string.Concat("Connection: ", _connection, "\r\n");
            }
            set
            {
                _connection = value;
            }
        }

        /// <summary>
        /// The Cache-Control general-header field is used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain. The directives specify behavior intended to prevent caches from adversely interfering with the request or response. These directives typically override the default caching algorithms. Cache directives are unidirectional in that the presence of a directive in a request does not imply that the same directive is to be given in the response.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
        /// </summary>
        public string CacheControl
        {
            get
            {
                return string.Concat("Cache-Control: ", _cacheControl, "\r\n");
            }
            set
            {
                _cacheControl = value;
            }
        }


        /// <summary>
        /// A user agent that wishes to authenticate itself with a server--
        /// usually, but not necessarily, after receiving a 401 response--does
        /// so by including an Authorization request-header field with the
        /// request.  The Authorization field value consists of credentials
        /// containing the authentication information of the user agent for
        /// the realm of the resource being requested.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.8
        /// </summary>
        public string Authorization
        {
            get
            {
                return string.Concat("Authorization: ", _authorization, "\r\n");
            }
            set
            {
                _authorization = value;
            }
        }

        /// <summary>
        /// The Allow entity-header field lists the set of methods supported
        /// by the resource identified by the Request-URI. The purpose of this
        /// field is strictly to inform the recipient of valid methods
        ///  associated with the resource. An Allow header field MUST be
        /// present in a 405 (Method Not Allowed) response.
        /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
        /// </summary>
        public string Allow
        {
            get
            {
                return string.Concat("Age: ", _allow, "\r\n");
            }
            set
            {
                _allow = value;
            }
        }

        /// <summary>
        ///The Age response-header field conveys the sender's estimate of the amount of time since the response (or its revalidation) was
        ///generated at the origin server. A cached response is "fresh" if its age does not exceed its freshness lifetime. Age values are calculated as specified in section 13.2.3.
        ///http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.6
        /// </summary>
        public string Age
        {
            get
            {
                return string.Concat("Age: ", _age, "\r\n");
            }
            set
            {
                _age = value;
            }
        }

        /// <summary>
        /// The Accept-Ranges response-header field allows the server to indicate its acceptance of range requests for a resource:        
        /// </summary>
        public string AcceptRanges
        {
            get
            {
                return string.Concat("Accept-Ranges: ", _acceptRanges, "\r\n");
            }
            set
            {
                _acceptRanges = value;
            }
        }

        public List<HttpEncoding> AcceptEncodings
        {
            get
            {
                return _acceptEncodings;
            }
            set
            {
                _acceptEncodings = value;
            }
        }

        public Charset AcceptCharset
        {
            get
            {
                return _acceptCharset;
            }
            set
            {
                _acceptCharset = value;
            }
        }

        public Media Accept
        {
            get
            {
                return _accept;
            }
            set
            {
                _accept = value;
            }
        }

        public string AcceptLanguage
        {
            get
            {

                return FormatRequestLine("Accept-Language", _acceptLanguage);
            }
            set
            {
                _acceptLanguage = value;
            }
        }

        public string Host
        {
            get
            {

                return FormatRequestLine("Host", _host);
            }
            set
            {
                _host = value;
            }
        }

        public string UserAgent
        {
            get
            {

                return FormatRequestLine("User-Agent", _userAgent);
            }
            set
            {
                _userAgent = value;
            }
        }


        #endregion
    }





    /// <summary>
    /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
    /// </summary>
    public class Language : AHeaderFields
    {
        public List<string> LanguageCode { get; set; }
        public List<string> Query { get; set; }

        public override string ToString()
        {
            string header = GetLine(LanguageCode);

            string temp = GetLine(Query);
            AppendLine(ref header, ref temp);

            header = string.Concat("Accept-Language: ", header, "\r\n");

            return header;
        }
    }

    /// <summary>
    /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
    /// </summary>
    public class HttpEncoding : AHeaderFields
    {
        public List<string> Codings { get; set; }
        public List<string> Query { get; set; }

        public override string ToString()
        {
            string header = GetLine(Codings);

            string temp = GetLine(Query);
            AppendLine(ref header, ref temp);

            header = string.Concat("Accept-Encoding: ", header, "\r\n");

            return header;
        }
    }



    public class Exp : AHeaderFields
    {
        public List<string> ChatSet { get; set; }
        public List<string> Query { get; set; }

        public override string ToString()
        {
            string header = GetLine(ChatSet);

            string temp = GetLine(Query);
            AppendLine(ref header, ref temp);


            header = string.Concat("Accept-Charset: ", header, "\r\n");

            return header;
        }

    }

    /// <summary>
    /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2
    /// </summary>
    public class Charset : AHeaderFields
    {
        public List<string> ChatSet { get; set; }
        public List<string> Query { get; set; }

        public override string ToString()
        {
            string header = GetLine(ChatSet);

            string temp = GetLine(Query);
            AppendLine(ref header, ref temp);


            header = string.Concat("Accept-Charset: ", header, "\r\n");

            return header;
        }

    }


    /// <summary>
    /// ref:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
    /// </summary>
    public class Media : AHeaderFields
    {
        /// <summary>
        ///        media-range    = ( "*/*"
        ///                | ( type "/" "*" )
        ///                | ( type "/" subtype )
        ///                ) *( ";" parameter )
        /// </summary>
        public List<string> MediaRange { get; set; }

        /// <summary>
        /// accept-params  = ";" "q" "=" qvalue *( accept-extension )
        /// </summary>
        public List<string> AcceptParams { get; set; }

        /// <summary>
        /// accept-extension = ";" token [ "=" ( token | quoted-string ) 
        /// </summary>
        public List<string> AcceptExtensions { get; set; }

        public Media()
        {
            MediaRange = new List<string>();
            AcceptParams = new List<string>();
            AcceptExtensions = new List<string>();
        }

        /// <summary>
        /// format Accept 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            string header = GetLine(MediaRange);

            string temp = GetLine(AcceptParams);
            AppendLine(ref header, ref temp);

            temp = GetLine(AcceptExtensions);
            AppendLine(ref header, ref temp);

            header = string.Concat("Accept: ", header, "\r\n");

            return header;
        }
    }

    public abstract class AHeaderFields
    {
        /// <summary>
        /// format Accept 
        /// </summary>
        /// <returns></returns>
        public abstract override string ToString();

        protected string GetLine(List<string> items)
        {
            string line = string.Empty;
            foreach (string str in items)
            {
                if (string.IsNullOrEmpty(line)) line = str;
                else line = string.Concat(line, ',', str);
            }
            return line;
        }

        protected void AppendLine(ref string headerline, ref string newline)
        {
            if (!string.IsNullOrEmpty(newline)) headerline = string.Concat(headerline, ";", newline);
        }
    }
}
